// use actix_web::{get, web, App, HttpServer, Responder};
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use rusqlite::{Connection};
use std::sync::Mutex;

struct AppStateWithCounter {
    counter: Mutex<i32>, // <- Mutex is necessary to mutate safely across threads
}


#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
#[derive(Debug)]
pub struct Item {
    pub id: i32,
    pub name: String,
    pub bh: String,
}
// fn main() {
//     let items=list_items();
//     // let rect1 = Rectangle { width: 30, height: 50 };
//     println!("rect1 is {:?}", items);
//     // get_items_json();
// }
fn list_items() ->String {
    let con = Connection::open("data.sqlite").unwrap();
    let sql:&str = "select id,name,bh from parts_item limit 3";
    let mut stmt = con.prepare(sql).unwrap();
    let person_iterator = stmt.query_map([], |row| {
        Ok(Item{
            id: row.get(0).unwrap(),
            name: row.get(1).unwrap(),
            bh: row.get(2).unwrap(),
        })
    }).unwrap();
    // let res=json::stringify(person_iterator);
    let mut res=String::new();
    res.push_str("[");
    for p in person_iterator {
        let p1=p.unwrap();
        res.push_str("{");
        // let s1=json::stringify(p1);
        let s1=format!("bh:{0}",p1.bh);
        println!("{:?}",s1);
        res.push_str(&s1);
        res.push_str("}");
        res.push_str(",");
    }
    res.push_str("]");
    println!("{:?}",res);
    return res;
}
// fn get_items_json(){
//     let items = get_items_result();
//     for item in items {
//         println!("Found item {:?}", item);
//     }
// }
// // fn get_items_result() -> Result<()> {
// //     let conn = Connection::open("data.sqlite")?;
// //     let mut stmt = conn.prepare(
// //         "select name,bh from parts_item limit 3",
// //     )?;
// //     let items = stmt.query_map([], |row| {
// //         Ok(Item {
// //             name: row.get(0)?,
// //             bh: row.get(1)?,
// //         })
// //     })?;
// //     for item in items {
// //         println!("Found cat {:?}", item);
// //     }
// //     Ok(())
// // }
#[get("/")]
async fn hello() -> impl Responder {
    let my_string = concat!(
        "<p><a href='/index.html'>index.html</a></p>",
        "<p><a href='/hey'>hey</a></p>",
        "<p><a href='/counter'>counter</a></p>",
        "<p><a href='/id_name/001/mary'>id_name</a></p>",
    );
    HttpResponse::Ok().body(my_string)
}

#[post("/echo")]
async fn echo(req_body: String) -> impl Responder {
    HttpResponse::Ok().body(req_body)
}

async fn manual_hello() -> impl Responder {
    HttpResponse::Ok().body("Hey there!")
}

#[get("/index.html")]
async fn index() -> impl Responder {
    let items = list_items();
    format!("{:?}",items)
}

async fn index_counter(data: web::Data<AppStateWithCounter>) -> String {
    let mut counter = data.counter.lock().unwrap(); // <- get counter's MutexGuard
    *counter += 1; // <- access counter inside MutexGuard

    format!("Request number: {counter}") // <- response with count
}

#[get("/id_name/{id}/{name}")]
async fn id_name(path:web::Path<(u32, String)>) -> impl Responder {
    let (id, name) = path.into_inner();
    format!("Hello {}! id:{}", name, id)
}

#[actix_web::main]
pub async fn main() -> std::io::Result<()> {
    let counter = web::Data::new(AppStateWithCounter {
        counter: Mutex::new(0),
    });
    HttpServer::new(move || {
        App::new()
            .app_data(counter.clone()) // <- register the created data
            .route("/counter", web::get().to(index_counter))
            .service(id_name)
            .service(index)
            .service(hello)
            .service(echo)
            .route("/hey", web::get().to(manual_hello))
    })
    .bind(("127.0.0.1", 8000))?
    .run()
    .await
}